package com.kingyun.gpsinspection.purificationservice.services.tdm.innerservice.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cqhilink.api.common.utils.UniqueUtil;
import com.kingyun.gpsinspection.purificationservice.common.utils.ConstantUtil;
import com.kingyun.gpsinspection.purificationservice.common.utils.FileTypeUtil;
import com.kingyun.gpsinspection.purificationservice.dao.mapper.tdm.*;
import com.kingyun.gpsinspection.purificationservice.facade.model.File;
import com.kingyun.gpsinspection.purificationservice.facade.model.jsm.EmployeeVo;
import com.kingyun.gpsinspection.purificationservice.facade.model.jsm.RedisValue;
import com.kingyun.gpsinspection.purificationservice.facade.model.tdm.*;
import com.kingyun.gpsinspection.purificationservice.facade.service.tdm.IBMBPMService;
import com.kingyun.gpsinspection.purificationservice.facade.service.tdm.TerritorialSupervisionService;
import com.kingyun.gpsinspection.purificationservice.facade.service.tdm.WorkOrderService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;

/**
 * 属地监督业务层
 * Created by sugongche on 2017/1/21.
 */
public class TerritorialSupervisionServiceImpl implements TerritorialSupervisionService {
    public Logger logger = LoggerFactory.getLogger(this.getClass());

    // BPM
    @Autowired
    public IBMBPMService ibmbpmService;
    @Autowired
    private TerritorialSupervisionMapper territorialSupervisionMapper;
    @Autowired
    public TaskLinkMapper taskLinkMapper;
    @Autowired
    public TdmWorkOrderMapper tdmWorkOrderMapper;
    @Autowired
    private TdmFileMapper tdmFileMapper;
    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private TdmTaskRelationMapper tdmTaskRelationMapper;

    /**
     * 保存
     * 注意：解开启事务，不能抛异常
     *
     * @param redisValue
     * @param employeeVo
     * @param territorialSupervision 属地监督
     * @param uploadFiles            上传附件
     * @param deletedFiles           删除附件
     * @param workOrderList
     * @param taskRelation
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public TerritorialSupervision save(RedisValue redisValue, EmployeeVo employeeVo, TerritorialSupervision territorialSupervision, String uploadFiles, String deletedFiles, List<WorkOrderVo> workOrderList, TaskRelation taskRelation) {
        int a = 0;

        //String username="deadmin";
        //String password="deadmin";

        String username = redisValue.getLoginName();//用户名
        String password = redisValue.getPassWord();//密码
        //开始流程
        String result = ibmbpmService.openBPM(employeeVo, territorialSupervision.getTaskType(), username, password, null);
        //如果没有权限直接返回99
        if (result.equals("WorkSpaceError")) {
            return null;
        }
        String piid = "";//流程实例ID
        String tkiid = "";//任务节点ID
        String name = ""; //第一个任务实例节点的名称

        //获得返回值
        JSONObject resultObj = JSONObject.parseObject(result);
        if (resultObj != null) {
            String status = (String) resultObj.get("status");
            //开始流程成功
            if (status != null && status.equals("200")) {
                //获取data属性的值
                JSONObject dataObj = (JSONObject) resultObj.get("data");
                //获取tasks属性的值：只有一个元素的数组，元素包含流程实例id和第一个节点的任务id
                JSONArray itemsArray = (JSONArray) dataObj.get("tasks");
                for (int i = 0; i < itemsArray.size(); i++) {//循环json数组
                    JSONObject ob = (JSONObject) itemsArray.get(i);//得到json对象
                    piid = ob.getString("piid");//piid这里是列名称，获取json对象中列名为piid的值
                    tkiid = ob.getString("tkiid");//tkiid这里是列名称，获取json对象中列名为tkiid的值
                    name = ob.getString("name");//name是列名称，获取json对象中列名为name的值
                }

                //执行第一个任务节点
                result = ibmbpmService.completeTask(username, password, tkiid, null);
                //获得返回值
                resultObj = JSONObject.parseObject(result);

                if (resultObj != null) {
                    status = (String) resultObj.get("status");
                    //完成任务成功
                    if (status != null && status.equals("200")) {
                        //第一步：保存任务信息
                        //保存属地监督：必须设置流程实例ID
                        territorialSupervision.setFlowId(piid);
                        //当前节点：从0开始
                        territorialSupervision.setNode((short) 0);
                        a += saveBean(employeeVo, territorialSupervision);
                        // 判断关联任务对象是否为空
                        if (StringUtils.isNotBlank(taskRelation.getMasterTaskId())) {
                            /// 关系表主键
                            taskRelation.setTaskRelationId(UniqueUtil.uuid());
                            // 主任务ID和主任务类型已经包含在relation对象中
                            taskRelation.setRelatedTaskId(territorialSupervision.getTerritorialSupervisionId());
                            taskRelation.setRelatedTaskType(territorialSupervision.getTaskType());
                            // 保存关联任务信息
                            tdmTaskRelationMapper.insert(taskRelation);
                        }

                        //第二步：保存附件；根据任务信息
                        a += saveAttach(territorialSupervision, uploadFiles, deletedFiles);

                        //第三步：保存任务环节和工单
                        TaskLink taskLink = new TaskLink();
                        taskLink.setPiPiid(piid);//流程实例ID
                        taskLink.setTkiid(tkiid);//任务节点ID
                        taskLink.setTaskLinkName(name);//任务节点名称
                        //第一个节点设置默认通过
                        taskLink.setAuditStatus((short) 1);
                        //保存任务相关信息：先保存任务环节，再保存工单
                        a += saveTaskLinkWorkOrder(employeeVo, territorialSupervision, taskLink, workOrderList);
                    } else {
                        logger.error("完成属地监督第一个任务节点失败！");
                    }
                } else {
                    logger.error("完成属地监督第一个任务节点无返回值！");
                }

            } else {
                logger.error("发起属地监督失败！");
            }
        } else {
            logger.error("发起属地监督无返回值！");
        }

        return territorialSupervision;
    }

    /**
     * 保存属地监督任务对象
     *
     * @param employeeVo
     * @param territorialSupervision
     * @return
     */
    public int saveBean(EmployeeVo employeeVo, TerritorialSupervision territorialSupervision) {
        int a = 0;
        territorialSupervision.setTerritorialSupervisionId(UniqueUtil.uuid());
        territorialSupervision.setCreateUserId(employeeVo.getEmployeeId());
        territorialSupervision.setModifyUserId(employeeVo.getEmployeeId());
        //-1 正在审核；1 审核通过；0审核不通过
        territorialSupervision.setAuditStatus((short) -1);
        //状态0正常；1是删除
        territorialSupervision.setIsDelete((short) 0);
        //状态1是启用；0是关闭
        territorialSupervision.setIsEnable((short) 1);
        //1 审核处理中；2 执行中；3 已完成
        territorialSupervision.setTaskStatus((short) 1);
        //创建时间
        territorialSupervision.setCreateTime(new Date());
        //修改时间
        territorialSupervision.setModifyTime(new Date());
        //新增发起任务信息
        a = territorialSupervisionMapper.insert(territorialSupervision);

        return a;
    }

    /**
     * 根据Bean的信息保存附件（新增和删除）
     *
     * @param territorialSupervision
     * @param uploadFiles
     * @return
     */
    public int saveAttach(TerritorialSupervision territorialSupervision, String uploadFiles, String deletedFiles) {
        int a = 0;

        //保存附件
        if (StringUtils.isNotBlank(uploadFiles)) {
            //强制转换成集合
            List<File> listFiles = JSON.parseArray(uploadFiles, File.class);
            //重新设置附件属性
            for (int i = 0; i < listFiles.size(); i++) {
                File _file = listFiles.get(i);
                //设置主键
                _file.setFileId(UniqueUtil.uuid());
                //设置业务数据id
                _file.setBusinessId(territorialSupervision.getTerritorialSupervisionId());
                _file.setFileType((short) FileTypeUtil.getFileTypeByFileName(_file.getFileName()));
            }
            //必须判断非空
            if (listFiles != null && listFiles.size() > 0) {
                a = tdmFileMapper.insertByList(listFiles);
            }
        }

        //需要删除的附件信息
        if (StringUtils.isNotBlank(deletedFiles)) {
            //强制转换成集合
            List<File> listFiles = JSON.parseArray(deletedFiles, File.class);
            if (listFiles != null && listFiles.size() > 0) {
                int len = listFiles.size();
                for (int i = 0; i < len; i++) {
                    File _file = listFiles.get(i);
                    a += tdmFileMapper.deleteByPrimaryKey(_file.getFileId());
                }
            }
        }

        return a;
    }

    /**
     * 更新
     *
     * @param redisValue
     * @param employeeVo
     * @param territorialSupervision
     * @param workOrderVoList
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int update(RedisValue redisValue, EmployeeVo employeeVo, TerritorialSupervision territorialSupervision, String uploadFiles, String deletedFiles, List<WorkOrderVo> workOrderVoList, TaskLink taskLink) {
        //标志变量
        int a = 0;

        //String username="deadmin";
        //String password="deadmin";

        String username = redisValue.getLoginName();//用户名
        String password = redisValue.getPassWord();//密码
        String result = ibmbpmService.completeTask(username, password, taskLink.getTkiid(), null);

        //处理返回值为空串：执行了但是没有返回值
        if ("".equals(result)) {
            logger.info("完成“" + taskLink.getTaskLinkName() + "”返回值为空串！");
        } else {
            //获得返回值
            JSONObject resultObj = JSONObject.parseObject(result);
            if (resultObj != null) {
                String status = (String) resultObj.get("status");
                //开始流程成功
                if (status != null && status.equals("200")) {
                    //第一步：更新任务信息；修改人必填
                    territorialSupervision.setModifyUserId(employeeVo.getEmployeeId());
                    a = territorialSupervisionMapper.updateByPrimaryKeyNew(territorialSupervision);

                    //第二步：更新附件信息：新增+删除
                    a += saveAttach(territorialSupervision, uploadFiles, deletedFiles);

                    //第三步：更新工单信息
                    a += updateWorkOrder(employeeVo, territorialSupervision, taskLink, workOrderVoList);

                    //第四步：更新任务环节信息；工单信息已经更新：此处无需再保存工单
                    //注意：必须拿到当前任务的信息，因为从页面上传来的任务信息没有node值
                    TerritorialSupervision territorialSupervisionNew = territorialSupervisionMapper.selectByPrimaryKey(territorialSupervision.getTerritorialSupervisionId());
                    a += saveTaskLinkWorkOrder(employeeVo, territorialSupervisionNew, taskLink, null);
                } else {
                    logger.error("完成“" + taskLink.getTaskLinkName() + "”返回状态非200！");
                }
            } else {
                logger.error("完成“" + taskLink.getTaskLinkName() + "”返回值非json字符串！！");
            }
        }

        return a;
    }

    /**
     * 更新任务的工单
     *
     * @param employeeVo
     * @param territorialSupervision
     * @param workOrderVoList
     * @return
     */
    public int updateWorkOrder(EmployeeVo employeeVo, TerritorialSupervision territorialSupervision, TaskLink taskLink, List<WorkOrderVo> workOrderVoList) {
        if (territorialSupervision == null) {
            return 0;
        }

        int a = 0;
        //删除该任务在数据库已有的工单
        a += tdmWorkOrderMapper.deleteByTaskId(territorialSupervision.getTerritorialSupervisionId());
        //保存页面的工单
        a += workOrderService.saveWorkOrderList(employeeVo, taskLink, workOrderVoList);

        return a;
    }

    /**
     * 根据主键查询bean
     *
     * @param territorialSupervisionId
     * @return
     */
    @Override
    public TerritorialSupervision queryBeanById(String territorialSupervisionId) throws Exception {
        if (StringUtils.isBlank(territorialSupervisionId)) {
            return null;
        }

        TerritorialSupervision territorialSupervision = territorialSupervisionMapper.selectByPrimaryKey(territorialSupervisionId);

        return territorialSupervision;
    }

    /**
     * 根据主键查询封装Bean
     *
     * @param territorialSupervisionId
     * @return
     */
    @Override
    public TerritorialSupervisionVo queryVoById(String territorialSupervisionId) throws Exception {
        if (StringUtils.isBlank(territorialSupervisionId)) {
            return null;
        }

        TerritorialSupervisionVo territorialSupervisionVo = territorialSupervisionMapper.selectByPrimaryKeyNew(territorialSupervisionId);

        return territorialSupervisionVo;
    }

    /**
     * 根据任务实例ID查询任务表和任务环节表
     *
     * @param piPiid
     * @return
     */
    @Override
    public TerritorialSupervisionVo findByPiPiid(String piPiid) {
        if (StringUtils.isBlank(piPiid)) {
            return null;
        }

        TerritorialSupervisionVo territorialSupervisionVo = territorialSupervisionMapper.findVoByPiPiid(piPiid);

        return territorialSupervisionVo;
    }

    /**
     * 审核时完成任务和保存信息
     *
     * @param redisValue
     * @param taskLink
     * @param workOrderList
     * @param territorialSupervision
     * @param employeeVo
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int saveByAudit(RedisValue redisValue, TaskLink taskLink, List<WorkOrderVo> workOrderList, TerritorialSupervision territorialSupervision, EmployeeVo employeeVo) {
        //用户信息
        //String username = "deadmin";
        //String password = "deadmin";

        String username = redisValue.getLoginName();
        String password = redisValue.getPassWord();

        String parameter = null;
        try {
            if (taskLink.getAuditStatus() != null) {
                //获取前台页面传来的审核是否通过的值：是用taskLink接收的
                parameter = URLEncoder.encode("{\"approved\":" + taskLink.getAuditStatus() + "}", "UTF-8");
            }
        } catch (UnsupportedEncodingException e) {
            logger.error("格式化输入参数错误", e);
        }
        String result = ibmbpmService.completeTask(username, password, taskLink.getTkiid(), parameter);

        //标志变量
        int a = 0;
        //处理返回值为空串：执行了但是没有返回值
        if ("".equals(result)) {
            logger.info("完成“" + taskLink.getTaskLinkName() + "”返回值为空串！");
        } else {
            //获得返回值
            JSONObject resultObj = JSONObject.parseObject(result);
            if (resultObj != null) {
                String status = (String) resultObj.get("status");
                //开始流程成功
                if (status != null && status.equals("200")) {
                    //处理任务
                    a = saveTaskLinkWorkOrder(employeeVo, territorialSupervision, taskLink, workOrderList);
                } else {
                    logger.error("完成“" + taskLink.getTaskLinkName() + "”返回状态非200！");
                }
            } else {
                logger.error("完成“" + taskLink.getTaskLinkName() + "”返回值非json字符串！！");
            }
        }

        return a;
    }

    /**
     * 现场操作
     *
     * @param redisValue
     * @param employeeVo
     * @param territorialSupervision
     * @param taskLink
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int saveBySpotOperation(RedisValue redisValue, EmployeeVo employeeVo, TerritorialSupervision territorialSupervision, TaskLink taskLink) {
        if (taskLink == null) {
            return 0;
        }

        //用户信息
        //String username = "deadmin";
        //String password = "deadmin";
        String username = redisValue.getLoginName();
        String password = redisValue.getPassWord();
        String result = ibmbpmService.completeTask(username, password, taskLink.getTkiid(), null);

        //标志变量
        int a = 0;
        //处理返回值为空串：执行了但是没有返回值
        if ("".equals(result)) {
            logger.info("完成“" + taskLink.getTaskLinkName() + "”返回值为空串！");
        } else {
            //获得返回值
            JSONObject resultObj = JSONObject.parseObject(result);
            if (resultObj != null) {
                String status = (String) resultObj.get("status");
                //开始流程成功
                if (status != null && status.equals("200")) {
                    a = saveTaskLinkWorkOrder(employeeVo, territorialSupervision, taskLink, null);
                } else {
                    logger.error("完成“" + taskLink.getTaskLinkName() + "”返回状态非200！");
                }
            } else {
                logger.error("完成“" + taskLink.getTaskLinkName() + "”返回值非json字符串！");
            }
        }

        return a;
    }

    /**
     * 保存任务相关信息：先保存任务环节，再保存工单
     *
     * @param employeeVo
     * @param territorialSupervision
     * @param taskLink
     * @param workOrderList
     * @return
     */
    public int saveTaskLinkWorkOrder(EmployeeVo employeeVo, TerritorialSupervision territorialSupervision, TaskLink taskLink, List<WorkOrderVo> workOrderList) {
        //标志变量
        int a = 0;
        //表单提交的审核状态
        Short auditStatus = taskLink.getAuditStatus();

        //添加任务环节：先
        taskLink.setTaskLinkId(UniqueUtil.uuid());
        //任务发起表存的是当前节点
        taskLink.setNode(territorialSupervision.getNode());
        taskLink.setTaskType(territorialSupervision.getTaskType());
        taskLink.setTaskId(territorialSupervision.getTerritorialSupervisionId());
        //没有审核：完成任务默认审核通过
        taskLink.setAuditStatus(auditStatus == null ? (short) 1 : auditStatus);
        //执行人ID：当前用户ID
        taskLink.setUserId(employeeVo.getEmployeeId());
        //执行人组织
        taskLink.setOrgId(employeeVo.getOrgId());
        a += taskLinkMapper.insertNew(taskLink);

        //保存工单：后
        a += workOrderService.saveWorkOrderList(employeeVo, taskLink, workOrderList);
        //没有审核或者审核通过：走到下一个节点，审核状态默认为通过
        if (auditStatus == null) {
            territorialSupervision.setAuditStatus((short) 1);
            a += territorialSupervisionMapper.updateAuditStatusById(territorialSupervision);
            //审核通过
        } else if (auditStatus != null && auditStatus == 1) {
            territorialSupervision.setAuditStatus((short) 1);
            a += territorialSupervisionMapper.updateAuditStatusById(territorialSupervision);
            //驳回：回到第一个节点
        } else if (auditStatus != null && auditStatus == 0) {
            territorialSupervision.setAuditStatus((short) 0);
            a += territorialSupervisionMapper.updateAuditStatusById(territorialSupervision);
        }

        //进入现场操作：必须结合下面两个条件
        if (auditStatus != null && auditStatus == 1 && ConstantUtil.AUDIT.equals(taskLink.getTaskLinkName())) {
            //进入现场操作：更新任务状态为执行中
            a += territorialSupervisionMapper.updateTaskStatusExecutedById(territorialSupervision);
            //更新工单状态：为可用
            a += tdmWorkOrderMapper.updateStatusEnableByTaskId(territorialSupervision.getTerritorialSupervisionId());
        }


        //完成任务时：更新任务状态和实际完成时间
        if (ConstantUtil.SPOT_OPERATION.equals(taskLink.getTaskLinkName())) {
            a += territorialSupervisionMapper.updateFinishById(territorialSupervision);
        }

        return a;
    }
}
